#include <cassert>

#include <logger.h>
#include <napi_call.h>
#include <node_api.h>

/* napi_value */
NAPI_MODULE_INIT(/* napi_env env, napi_value exports */)
{
    bool success = false;
    napi_value key = nullptr;
    napi_value val = nullptr;
    NAPI_CALL(env, napi_create_string_utf8(env, "key", NAPI_AUTO_LENGTH, &key));

    napi_property_descriptor props[] = {
        {
            .utf8name = "prop",
            .name = nullptr,
            .method = nullptr,
            .getter = nullptr,
            .setter = nullptr,
            .value = key,
            .attributes = napi_enumerable,
            .data = nullptr,
        },
    };
    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(props) / sizeof(*props), props));

    NAPI_CALL(env, napi_set_property(env, exports, key, key));
    NAPI_CALL(env, napi_get_property(env, exports, key, &val));
    NAPI_CALL(env, napi_strict_equals(env, key, val, &success));
    assert(success == true);
    NAPI_CALL(env, napi_has_property(env, exports, key, &success));
    assert(success == true);
    NAPI_CALL(env, napi_delete_property(env, exports, key, &success));
    assert(success == true);

    NAPI_CALL(env, napi_set_named_property(env, exports, "key2", key));
    NAPI_CALL(env, napi_get_named_property(env, exports, "key2", &val));
    NAPI_CALL(env, napi_has_named_property(env, exports, "key", &success));
    assert(success == false);
    NAPI_CALL(env, napi_has_named_property(env, exports, "key2", &success));
    assert(success == true);
    NAPI_CALL(env, napi_has_named_property(env, exports, "prop", &success));
    assert(success == true);

    NAPI_CALL(env, napi_set_element(env, exports, 1, key));
    NAPI_CALL(env, napi_set_element(env, exports, 2, key));
    NAPI_CALL(env, napi_get_element(env, exports, 1, &val));
    NAPI_CALL(env, napi_strict_equals(env, key, val, &success));
    assert(success == true);
    NAPI_CALL(env, napi_delete_element(env, exports, 1, &success));
    assert(success == true);
    NAPI_CALL(env, napi_delete_element(env, exports, 3, &success));
    assert(success == true);

    napi_value keys = nullptr;
    NAPI_CALL(env, napi_get_property_names(env, exports, &keys));
    uint32_t len = 0;
    NAPI_CALL(env, napi_get_array_length(env, keys, &len));
    char buf[32];
    size_t buflen = 0;
    for (uint32_t i = 0; i < len; i++) {
        NAPI_CALL(env, napi_get_element(env, keys, i, &val));
        NAPI_CALL(env, napi_get_value_string_utf8(env, val, buf, sizeof(buf), &buflen));
        if (buflen > 0) {
            VALUE_LOGGER(buflen);
            VALUE_LOGGER(buf);
        }
    }
    // buflen: 1
    // buf: 2
    // buflen: 4
    // buf: prop
    // buflen: 4
    // buf: key2

    return exports;
}
